package com.tmt.im.manager.service;

import com.alibaba.fastjson2.JSONObject;
import com.tmt.data.jpa.service.TmtJpaDataService;
import com.tmt.im.common.enums.CustomizedMsgCode;
import com.tmt.im.common.pojo.IMUserPoJo;
import com.tmt.im.common.pojo.SystemNotifyKey;
import com.tmt.im.common.pojo.SystemNotifyPoJo;
import com.tmt.im.common.yunxin.IYunXinMsgSender;
import com.tmt.im.jpa.entity.SystemNotify;
import com.tmt.im.jpa.repository.SystemNotifyRepo;
import com.tmt.im.manager.controller.vo.SlideQueryRequest;
import com.tmt.im.manager.controller.vo.SlideQuerySystemNotifyResponse;
import com.tmt.im.manager.controller.vo.SystemNotifyVo;
import com.tmt.im.manager.controller.vo.SystemNotifyVoEx;
import com.tmt.im.manager.helper.IgniteQueryHelper;
import com.tmt.im.manager.helper.PrincipalHelper;
import com.tmt.im.manager.mapstruct.SystemNotifyMapStruct;
import com.tmt.springboot.common.helper.IdSnowFlake;
import com.tmt.springboot.common.restful.ExecuteResult;
import com.tmt.springboot.common.restful.IExecuteResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.security.Principal;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/9/29 18:50
 * @Version 1.0
 **/
@Service
@Slf4j
public class SystemNotifyService extends TmtJpaDataService<SystemNotify, Long> {

    private final IgniteCache<SystemNotifyKey, SystemNotifyPoJo> notifyCache;

    private final IgniteCache<Long, IMUserPoJo> userCache;

    private final SystemNotifyMapStruct notifyMapStruct;

    private final IYunXinMsgSender iYunXinMsgSender;

    public SystemNotifyService(Ignite ignite,
                               SystemNotifyRepo systemNotifyRepo,
                               SystemNotifyMapStruct notifyMapStruct,
                               IYunXinMsgSender iYunXinMsgSender) {
        super(systemNotifyRepo);
        notifyCache = ignite.cache(SystemNotifyPoJo.CACHE_NAME);
        userCache = ignite.cache(IMUserPoJo.CACHE_NAME);
        this.notifyMapStruct = notifyMapStruct;
        this.iYunXinMsgSender = iYunXinMsgSender;
    }

    public IExecuteResult<SystemNotifyVoEx> createSystemNotify(SystemNotifyVo vo, Principal principal) {
        try {
            Long currentUserId = PrincipalHelper.getCurrentUserId(principal);
            SystemNotifyPoJo notifyPoJo = new SystemNotifyPoJo();
            BeanUtils.copyProperties(vo, notifyPoJo);
            notifyPoJo.setId(IdSnowFlake.getId());
            notifyPoJo.setMid(notifyPoJo.getId());
            notifyPoJo.setType(vo.getType().name());
            notifyPoJo.setCreatorId(currentUserId);
            notifyPoJo.setVersion(0L);
            notifyPoJo.setCreateTime(new Timestamp(System.currentTimeMillis()));
            notifyPoJo.setInsert(true);
            notifyCache.put(notifyPoJo.getKey(), notifyPoJo);

            //向所有用户发送滚屏通知。
            JSONObject json = new JSONObject();
            json.put("type", CustomizedMsgCode.GROUP_ROLL_INFORM.getType());
            json.put("msg", "新增滚屏通知");
            StringBuilder error = new StringBuilder();

            String sql = MessageFormat.format("select * from {0} where id > ?", IMUserPoJo.CACHE_NAME);
            List<IMUserPoJo> userPoJos = IgniteQueryHelper.findAllBy(sql, new Object[]{0}, IMUserPoJo.class, userCache);
            for (IMUserPoJo user : userPoJos) {
                error.setLength(0);
                if (!iYunXinMsgSender.sendCustomizedMsg(currentUserId, user.getId(), json, error)) {
                    log.error("-----发送新增滚屏通知失败-----" + error);
                }
            }

            SystemNotifyVoEx voEx = notifyMapStruct.toSystemNotifyVoEx(notifyPoJo);
            return ExecuteResult.success(voEx);
        } catch (Exception ex) {
            return ExecuteResult.failure(ex.getMessage(), null);
        }
    }

    public IExecuteResult<SystemNotifyVoEx> updateSystemNotify(SystemNotifyVo vo, Principal principal) {
        try {
            String sql = MessageFormat.format("select * from {0} where mid = ?", SystemNotifyPoJo.CACHE_NAME);
            SystemNotifyPoJo notifyPoJo = IgniteQueryHelper.findOneBy(sql, new Object[]{vo.getId()}, SystemNotifyPoJo.class, notifyCache);
            if (notifyPoJo == null) {
                return ExecuteResult.failure("目标系统通知不存在", null);
            }

            if (StringUtils.hasText(vo.getTitle())) {
                notifyPoJo.setTitle(vo.getTitle());
            }

            if (StringUtils.hasText(vo.getContent())) {
                notifyPoJo.setContent(vo.getContent());
            }

            if (vo.getType() != null) {
                notifyPoJo.setType(vo.getType().name());
            }

            notifyPoJo.setVersion(notifyPoJo.getVersion() + 1);
            notifyPoJo.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            notifyPoJo.setInsert(false);
            notifyCache.put(notifyPoJo.getKey(), notifyPoJo);

            SystemNotifyVoEx voEx = notifyMapStruct.toSystemNotifyVoEx(notifyPoJo);
            return ExecuteResult.success(voEx);
        } catch (Exception ex) {
            return ExecuteResult.failure(ex.getMessage(), null);
        }
    }

    public IExecuteResult<Boolean> deleteSystemNotify(Long id, Principal principal) {
        String sql = MessageFormat.format("select * from {0} where mid = ?", SystemNotifyPoJo.CACHE_NAME);
        SystemNotifyPoJo notifyPoJo = IgniteQueryHelper.findOneBy(sql, new Object[]{id}, SystemNotifyPoJo.class, notifyCache);
        if (notifyPoJo != null) {
            notifyCache.remove(notifyPoJo.getKey());
            return ExecuteResult.success(true);
        }
        return ExecuteResult.failure("目标系统通知不存在", false);
    }


    public IExecuteResult<SlideQuerySystemNotifyResponse> slideQuerySystemNotifies(SlideQueryRequest request, Principal principal) {
        if (request.getStartId() == null || request.getStartId() <= 0) {
            request.setStartId(Long.MAX_VALUE);
        }

        String flag1 = request.getBackward() ? ">" : "<";
        String flag2 = request.getBackward() ? "asc" : "desc";

        String sql = MessageFormat.format("select * from {0} where  mid {1} ? order by mid {2} limit ?, ?",
                SystemNotifyPoJo.CACHE_NAME, flag1, flag2);
        Object[] params = new Object[]{request.getStartId(), 0, request.getWindowSize()};
        List<SystemNotifyPoJo> notifyPoJos = IgniteQueryHelper.findAllBy(sql, params, SystemNotifyPoJo.class, notifyCache);
        if (CollectionUtils.isEmpty(notifyPoJos)) {
            SlideQuerySystemNotifyResponse response = new SlideQuerySystemNotifyResponse(new ArrayList<>());
            BeanUtils.copyProperties(request, response);
            return ExecuteResult.success("没有更多的数据了", response);
        }

        if ("desc".equals(flag2)) {
            //如果是向前查询则需要倒序一下，保持升序排序。
            notifyPoJos = notifyPoJos.stream().sorted(Comparator.comparingLong(SystemNotifyPoJo::getId)).toList();
        }

        List<SystemNotifyVoEx> list = notifyMapStruct.toSystemNotifyVoExs(notifyPoJos);
        SlideQuerySystemNotifyResponse response = new SlideQuerySystemNotifyResponse(list);
        BeanUtils.copyProperties(request, response);
        return ExecuteResult.success(response);
    }

}
